Системное программирование

Работа с сокетами в Linux

Системное программирование

Работа с сокетами в Linux: Сетевое программирование

Сокеты - это фундаментальный механизм для сетевого и межпроцессного взаимодействия в Linux. Эта лекция охватывает создание сетевых приложений, работу с TCP и UDP протоколами, и различные аспекты сетевого программирования в Linux.

Работа с сокетами в Linux
Системное программирование

План лекции:

  1. Что такое сокеты?
  2. Типы сокетов
  3. Сетевые протоколы: TCP и UDP
  4. Системные вызовы для работы с сокетами
  5. Создание TCP-сервера
  6. Создание TCP-клиента
  7. Создание UDP-сервера и клиента
  8. Доменные сокеты (Unix Domain Sockets)
  9. Неблокирующие сокеты и многопоточность
  10. Ошибки и обработка исключительных ситуаций
  11. Практические примеры
  12. Заключение и рекомендации
Работа с сокетами в Linux
Системное программирование

1. Что такое сокеты?

Сокет (socket) - это абстракция, представляющая конечную точку сетевого соединения. Сокет описывается следующими параметрами:

  • Домен (Domain) - семейство протоколов (AF_INET для IPv4, AF_INET6 для IPv6, AF_UNIX для локальных сокетов)
  • Тип (Type) - тип взаимодействия (SOCK_STREAM для TCP, SOCK_DGRAM для UDP)
  • Протокол (Protocol) - конкретный протокол (обычно 0 для выбора по умолчанию)

Сокеты предоставляют универсальный интерфейс для сетевого взаимодействия между процессами, независимо от того, находятся ли они на одной машине или в разных сетях.

Работа с сокетами в Linux
Системное программирование

2. Типы сокетов

Основные типы сокетов:

  • SOCK_STREAM - ориентированный на установление соединения, надежный, двунаправленный поток байтов (TCP)
  • SOCK_DGRAM - без установления соединения, ненадежный, фиксированный размер сообщений (UDP)
  • SOCK_RAW - предоставляет доступ к низкоуровневым протоколам и интерфейсам
  • SOCK_SEQPACKET - как SOCK_STREAM, но сохраняет границы сообщений
Работа с сокетами в Linux
Системное программирование

3. Сетевые протоколы: TCP и UDP

TCP (Transmission Control Protocol):

  • Надежная доставка данных
  • Установление соединения (трехэтапное рукопожатие)
  • Упорядочивание данных
  • Контроль потока и перегрузки
  • Подходит для приложений, требующих надежности (HTTP, FTP, SSH)

UDP (User Datagram Protocol):

  • Без установления соединения
  • Быстрая передача данных
  • Нет гарантии доставки
  • Нет упорядочивания
  • Подходит для приложений, где важна скорость (DNS, видеостриминг, игры)
Работа с сокетами в Linux
Системное программирование

4. Системные вызовы для работы с сокетами

Основные системные вызовы:

  • socket() - создание сокета
  • bind() - привязка сокета к адресу
  • listen() - перевод сокета в режим прослушивания
  • accept() - принятие входящего соединения
  • connect() - установление соединения с сервером
  • send()/recv() - отправка и получение данных (TCP)
  • sendto()/recvfrom() - отправка и получение данных (UDP)
  • close() - закрытие сокета
Работа с сокетами в Linux
Системное программирование

Создание сокета:

#include <sys/socket.h>
#include <netinet/in.h>

int socket(int domain, int type, int protocol);

// Примеры:
int tcp_socket = socket(AF_INET, SOCK_STREAM, 0);
int udp_socket = socket(AF_INET, SOCK_DGRAM, 0);
int unix_socket = socket(AF_UNIX, SOCK_STREAM, 0);

Возвращает дескриптор сокета или -1 при ошибке.

Работа с сокетами в Linux
Системное программирование

Структура sockaddr_in:

#include <netinet/in.h>

struct sockaddr_in {
    sa_family_t    sin_family;   // AF_INET
    in_port_t      sin_port;     // Порт (в сетевом порядке байт)
    struct in_addr sin_addr;     // IP-адрес
    char           sin_zero[8];  // Заполняется нулями
};

struct in_addr {
    uint32_t       s_addr;       // IP-адрес в сетевом порядке байт
};

// Пример заполнения:
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(8080);
server_addr.sin_addr.s_addr = INADDR_ANY;
memset(server_addr.sin_zero, 0, sizeof(server_addr.sin_zero));
Работа с сокетами в Linux
Системное программирование

5. Создание TCP-сервера

Алгоритм работы TCP-сервера:

  1. Создать сокет
  2. Привязать сокет к адресу и порту
  3. Перевести сокет в режим прослушивания
  4. Принимать входящие соединения
  5. Обрабатывать клиентов
  6. Закрывать соединения
Работа с сокетами в Linux
Системное программирование

Пример TCP-сервера:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define PORT 8080
#define BUFFER_SIZE 1024

int main() {
    int server_fd, new_socket;
    struct sockaddr_in address;
    int opt = 1;
    int addrlen = sizeof(address);
    char buffer[BUFFER_SIZE] = {0};
    
    // Создание сокета
    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
        perror("socket failed");
        exit(EXIT_FAILURE);
    }
Работа с сокетами в Linux
Системное программирование
    // Настройка сокета
    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) {
        perror("setsockopt");
        exit(EXIT_FAILURE);
    }
    
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(PORT);
    
    // Привязка сокета
    if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
        perror("bind failed");
        exit(EXIT_FAILURE);
    }
Работа с сокетами в Linux
Системное программирование
    // Перевод в режим прослушивания
    if (listen(server_fd, 3) < 0) {
        perror("listen");
        exit(EXIT_FAILURE);
    }
    
    printf("Server listening on port %d\n", PORT);
    
    // Принятие входящего соединения
    if ((new_socket = accept(server_fd, (struct sockaddr *)&address, 
                           (socklen_t*)&addrlen)) < 0) {
        perror("accept");
        exit(EXIT_FAILURE);
    }
Работа с сокетами в Linux
Системное программирование
    // Чтение данных от клиента
    int valread = read(new_socket, buffer, BUFFER_SIZE);
    printf("Received: %s\n", buffer);
    
    // Отправка ответа клиенту
    char *hello = "Hello from server";
    send(new_socket, hello, strlen(hello), 0);
    printf("Hello message sent\n");
    
    // Закрытие сокетов
    close(new_socket);
    close(server_fd);
    
    return 0;
}
Работа с сокетами в Linux
Системное программирование

6. Создание TCP-клиента

Алгоритм работы TCP-клиента:

  1. Создать сокет
  2. Установить соединение с сервером
  3. Отправить данные серверу
  4. Получить ответ от сервера
  5. Закрыть соединение
Работа с сокетами в Linux
Системное программирование

Пример TCP-клиента:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define PORT 8080
#define BUFFER_SIZE 1024

int main() {
    int sock = 0;
    struct sockaddr_in serv_addr;
    char *hello = "Hello from client";
    char buffer[BUFFER_SIZE] = {0};
    
    // Создание сокета
    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        printf("\n Socket creation error \n");
        return -1;
    }
Работа с сокетами в Linux
Системное программирование
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(PORT);
    
    // Преобразование IP-адреса из текста в бинарный формат
    if(inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) <= 0) {
        printf("\nInvalid address/ Address not supported \n");
        return -1;
    }
    
    // Установление соединения
    if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
        printf("\nConnection Failed \n");
        return -1;
    }
Работа с сокетами в Linux
Системное программирование
    // Отправка данных серверу
    send(sock, hello, strlen(hello), 0);
    printf("Hello message sent\n");
    
    // Чтение ответа от сервера
    int valread = read(sock, buffer, BUFFER_SIZE);
    printf("Received: %s\n", buffer);
    
    // Закрытие сокета
    close(sock);
    
    return 0;
}
Работа с сокетами в Linux
Системное программирование

7. Создание UDP-сервера и клиента

UDP-сервер:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define PORT 8080
#define BUFFER_SIZE 1024

int main() {
    int sockfd;
    struct sockaddr_in servaddr, cliaddr;
    char buffer[BUFFER_SIZE];
    socklen_t len;
    
    // Создание UDP-сокета
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0) {
        perror("socket creation failed");
        exit(EXIT_FAILURE);
    }
Работа с сокетами в Linux
Системное программирование
    memset(&servaddr, 0, sizeof(servaddr));
    memset(&cliaddr, 0, sizeof(cliaddr));
    
    // Заполнение информации о сервере
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = INADDR_ANY;
    servaddr.sin_port = htons(PORT);
    
    // Привязка сокета
    if (bind(sockfd, (const struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
        perror("bind failed");
        exit(EXIT_FAILURE);
    }
Работа с сокетами в Linux
Системное программирование
    len = sizeof(cliaddr);
    
    while (1) {
        int n = recvfrom(sockfd, buffer, BUFFER_SIZE, 0,
                        (struct sockaddr *)&cliaddr, &len);
        buffer[n] = '\0';
        printf("Client: %s\n", buffer);
        
        // Отправка ответа клиенту
        char *response = "Hello from UDP server";
        sendto(sockfd, response, strlen(response), 0,
               (const struct sockaddr *)&cliaddr, len);
    }
    
    close(sockfd);
    return 0;
}
Работа с сокетами в Linux
Системное программирование

UDP-клиент:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define PORT 8080
#define BUFFER_SIZE 1024

int main() {
    int sockfd;
    struct sockaddr_in servaddr;
    char buffer[BUFFER_SIZE];
    
    // Создание UDP-сокета
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0) {
        perror("socket creation failed");
        exit(EXIT_FAILURE);
    }
Работа с сокетами в Linux
Системное программирование
    memset(&servaddr, 0, sizeof(servaddr));
    
    // Заполнение информации о сервере
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(PORT);
    servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
    
    // Отправка данных серверу
    char *message = "Hello UDP server";
    sendto(sockfd, message, strlen(message), 0,
           (const struct sockaddr *)&servaddr, sizeof(servaddr));
Работа с сокетами в Linux
Системное программирование
    // Получение ответа от сервера
    int n = recvfrom(sockfd, buffer, BUFFER_SIZE, 0, NULL, NULL);
    buffer[n] = '\0';
    printf("Server response: %s\n", buffer);
    
    close(sockfd);
    return 0;
}
Работа с сокетами в Linux
Системное программирование

8. Доменные сокеты (Unix Domain Sockets)

Доменные сокеты используются для взаимодействия процессов на одной машине и работают быстрее сетевых сокетов.

Сервер на Unix Domain Sockets:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>

#define SOCKET_PATH "/tmp/unix_socket"
#define BUFFER_SIZE 1024

int main() {
    int server_fd, client_fd;
    struct sockaddr_un server_addr, client_addr;
    char buffer[BUFFER_SIZE];
    socklen_t client_len = sizeof(client_addr);
Работа с сокетами в Linux
Системное программирование
    // Создание сокета
    server_fd = socket(AF_UNIX, SOCK_STREAM, 0);
    if (server_fd == -1) {
        perror("socket");
        exit(EXIT_FAILURE);
    }
    
    // Настройка адреса
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sun_family = AF_UNIX;
    strncpy(server_addr.sun_path, SOCKET_PATH, sizeof(server_addr.sun_path) - 1);
    
    // Удаление существующего файла сокета
    unlink(SOCKET_PATH);
Работа с сокетами в Linux
Системное программирование
    // Привязка
    if (bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
        perror("bind");
        exit(EXIT_FAILURE);
    }
    
    // Прослушивание
    if (listen(server_fd, 5) == -1) {
        perror("listen");
        exit(EXIT_FAILURE);
    }
Работа с сокетами в Linux
Системное программирование
    printf("Unix domain server listening on %s\n", SOCKET_PATH);
    
    // Принятие соединения
    client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &client_len);
    if (client_fd == -1) {
        perror("accept");
        exit(EXIT_FAILURE);
    }
    
    // Чтение данных
    int n = read(client_fd, buffer, BUFFER_SIZE);
    buffer[n] = '\0';
    printf("Received: %s\n", buffer);
    
    // Отправка ответа
    char *response = "Hello from Unix domain server";
    write(client_fd, response, strlen(response));
    
    // Закрытие
    close(client_fd);
    close(server_fd);
    unlink(SOCKET_PATH);
    
    return 0;
}
Работа с сокетами в Linux
Системное программирование

9. Неблокирующие сокеты и многопоточность

Установление неблокирующего режима:

#include <fcntl.h>

// Метод 1: Использование fcntl
int flags = fcntl(socket_fd, F_GETFL, 0);
fcntl(socket_fd, F_SETFL, flags | O_NONBLOCK);

// Метод 2: Использование setsockopt
int opt = 1;
ioctl(socket_fd, FIONBIO, &opt);
Работа с сокетами в Linux
Системное программирование

Многопоточный сервер:

#include <pthread.h>

void *handle_client(void *arg) {
    int client_socket = *(int*)arg;
    char buffer[1024];
    
    int n = read(client_socket, buffer, sizeof(buffer));
    // Обработка данных
    
    close(client_socket);
    free(arg);
    return NULL;
}

int main() {
    int server_socket = socket(AF_INET, SOCK_STREAM, 0);
    // ... настройка сервера ...
    
    while (1) {
        int *client_socket = malloc(sizeof(int));
        *client_socket = accept(server_socket, NULL, NULL);
        
        pthread_t thread;
        pthread_create(&thread, NULL, handle_client, client_socket);
        pthread_detach(thread);
    }
    
    close(server_socket);
    return 0;
}
Работа с сокетами в Linux
Системное программирование

10. Ошибки и обработка исключительных ситуаций

Общие ошибки сокетов:

#include <errno.h>
#include <string.h>

void handle_socket_error(const char *operation) {
    switch (errno) {
        case EACCES:
            fprintf(stderr, "%s: Permission denied\n", operation);
            break;
        case EADDRINUSE:
            fprintf(stderr, "%s: Address already in use\n", operation);
            break;
        case ECONNREFUSED:
            fprintf(stderr, "%s: Connection refused\n", operation);
            break;
        case ETIMEDOUT:
            fprintf(stderr, "%s: Connection timed out\n", operation);
            break;
        case EHOSTUNREACH:
            fprintf(stderr, "%s: Host is unreachable\n", operation);
            break;
        default:
            perror(operation);
    }
}
Работа с сокетами в Linux
Системное программирование

Обработка сигналов:

#include <signal.h>

volatile sig_atomic_t server_running = 1;

void signal_handler(int sig) {
    if (sig == SIGINT || sig == SIGTERM) {
        server_running = 0;
    }
}

int main() {
    signal(SIGINT, signal_handler);
    signal(SIGTERM, signal_handler);
    
    int server_socket = socket(AF_INET, SOCK_STREAM, 0);
    // ... настройка сервера ...
    
    while (server_running) {
        int client_socket = accept(server_socket, NULL, NULL);
        if (client_socket < 0) {
            if (errno == EINTR) continue;  // Прерывание системного вызова
            break;
        }
        // Обработка клиента
        close(client_socket);
    }
    
    close(server_socket);
    return 0;
}
Работа с сокетами в Linux
Системное программирование

11. Практические примеры

Пример 1: Простой HTTP-сервер

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define PORT 8080

const char *http_response = 
    "HTTP/1.1 200 OK\r\n"
    "Content-Type: text/html\r\n"
    "Content-Length: 100\r\n"
    "\r\n"
    "<html><body><h1>Hello from C HTTP Server!</h1></body></html>";

int main() {
    int server_fd, client_fd;
    struct sockaddr_in address;
    int addrlen = sizeof(address);
    char buffer[1024] = {0};
    
    server_fd = socket(AF_INET, SOCK_STREAM, 0);
    
    int opt = 1;
    setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
    
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(PORT);
    
    bind(server_fd, (struct sockaddr *)&address, sizeof(address));
    listen(server_fd, 3);
    
    printf("HTTP Server listening on port %d\n", PORT);
    
    while (1) {
        client_fd = accept(server_fd, (struct sockaddr *)&address, 
                          (socklen_t*)&addrlen);
        
        // Читаем HTTP-запрос
        read(client_fd, buffer, 1024);
        printf("Request:\n%s\n", buffer);
        
        // Отправляем HTTP-ответ
        write(client_fd, http_response, strlen(http_response));
        
        close(client_fd);
    }
    
    close(server_fd);
    return 0;
}
Работа с сокетами в Linux
Системное программирование

Пример 2: Клиент для получения времени (TCP)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

#define PORT 13  // Стандартный порт службы time

int main(int argc, char *argv[]) {
    if (argc != 2) {
        fprintf(stderr, "Usage: %s hostname\n", argv[0]);
        return 1;
    }
    
    int sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock < 0) {
        perror("socket");
        return 1;
    }
    
    // Получение IP-адреса по имени хоста
    struct hostent *host = gethostbyname(argv[1]);
    if (host == NULL) {
        fprintf(stderr, "Cannot resolve hostname: %s\n", argv[1]);
        return 1;
    }
    
    struct sockaddr_in server_addr;
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(PORT);
    memcpy(&server_addr.sin_addr, host->h_addr_list[0], host->h_length);
    
    printf("Connecting to %s:%d\n", argv[1], PORT);
    
    if (connect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
        perror("connect");
        close(sock);
        return 1;
    }
    
    // Чтение времени от сервера
    char buffer[256];
    int n = read(sock, buffer, sizeof(buffer) - 1);
    if (n > 0) {
        buffer[n] = '\0';
        printf("Server time: %s", buffer);
    }
    
    close(sock);
    return 0;
}
Работа с сокетами в Linux
Системное программирование

Пример 3: UDP-чат

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>

#define PORT 8888
#define BUFFER_SIZE 1024

int sockfd;
struct sockaddr_in peer_addr;

void *receive_messages(void *arg) {
    char buffer[BUFFER_SIZE];
    socklen_t len = sizeof(peer_addr);
    
    while (1) {
        int n = recvfrom(sockfd, buffer, BUFFER_SIZE, 0,
                        (struct sockaddr *)&peer_addr, &len);
        if (n > 0) {
            buffer[n] = '\0';
            printf("\rPeer: %s\nYou: ", buffer);
            fflush(stdout);
        }
    }
    return NULL;
}

int main(int argc, char *argv[]) {
    if (argc != 3) {
        fprintf(stderr, "Usage: %s <local_port> <peer_ip:port>\n", argv[0]);
        return 1;
    }
    
    // Разбор аргументов
    int local_port = atoi(argv[1]);
    char *peer_ip = strtok(argv[2], ":");
    int peer_port = atoi(strtok(NULL, ":"));
    
    // Создание UDP-сокета
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0) {
        perror("socket");
        return 1;
    }
    
    // Привязка к локальному порту
    struct sockaddr_in local_addr;
    local_addr.sin_family = AF_INET;
    local_addr.sin_addr.s_addr = INADDR_ANY;
    local_addr.sin_port = htons(local_port);
    bind(sockfd, (struct sockaddr *)&local_addr, sizeof(local_addr));
    
    // Настройка адреса пира
    peer_addr.sin_family = AF_INET;
    peer_addr.sin_addr.s_addr = inet_addr(peer_ip);
    peer_addr.sin_port = htons(peer_port);
    
    printf("UDP Chat started. Local port: %d, Peer: %s:%d\n", 
           local_port, peer_ip, peer_port);
    printf("Type messages and press Enter to send. Type 'quit' to exit.\n");
    
    // Запуск потока для получения сообщений
    pthread_t receive_thread;
    pthread_create(&receive_thread, NULL, receive_messages, NULL);
    
    // Отправка сообщений
    char message[BUFFER_SIZE];
    while (1) {
        printf("You: ");
        fflush(stdout);
        
        if (fgets(message, BUFFER_SIZE, stdin) != NULL) {
            // Удаление символа новой строки
            message[strcspn(message, "\n")] = 0;
            
            if (strcmp(message, "quit") == 0) {
                break;
            }
            
            sendto(sockfd, message, strlen(message), 0,
                   (struct sockaddr *)&peer_addr, sizeof(peer_addr));
        }
    }
    
    close(sockfd);
    return 0;
}
Работа с сокетами в Linux
Системное программирование

12. Заключение и рекомендации

Выбор типа сокета:

  • TCP - когда нужна надежность и упорядоченность данных (веб-сервисы, файловые передачи)
  • UDP - когда важна скорость и можно потерять некоторые данные (видеостриминг, игры, DNS)
  • Unix Domain Sockets - для взаимодействия процессов на одной машине (быстрее сетевых)
Работа с сокетами в Linux
Системное программирование

Рекомендации по проектированию:

  1. Всегда проверяйте возвращаемые значения системных вызовов
  2. Используйте неблокирующий I/O или многопоточность для обработки нескольких клиентов
  3. Обрабатывайте сигналы для корректного завершения сервера
  4. Освобождайте ресурсы (закрывайте сокеты, освобождайте память)
  5. Используйте таймауты для предотвращения зависаний
  6. Проверяйте границы буферов для предотвращения переполнений
Работа с сокетами в Linux
Системное программирование

Полезные функции:

// Преобразование адресов
inet_pton(AF_INET, "192.168.1.1", &addr.sin_addr);
inet_ntop(AF_INET, &addr.sin_addr, buffer, sizeof(buffer));

// Получение информации о хосте
struct hostent *host = gethostbyname("example.com");

// Работа с опциями сокета
int opt = 1;
setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

// Получение информации о сокете
struct sockaddr_in local_addr;
socklen_t addr_len = sizeof(local_addr);
getsockname(socket_fd, (struct sockaddr*)&local_addr, &addr_len);
Работа с сокетами в Linux
Системное программирование

Дополнительные темы для изучения:

  • select(), poll(), epoll() - мультиплексирование ввода/вывода
  • SSL/TLS - шифрование сокетов
  • IPv6 - работа с адресами нового поколения
  • Broadcast и Multicast - групповая рассылка
  • Raw-сокеты - низкоуровневое сетевое программирование
  • Netlink-сокеты - взаимодействие с ядром Linux

Сокеты являются фундаментом сетевого программирования и позволяют создавать мощные распределенные приложения в Linux.

Работа с сокетами в Linux